#Include EC-P.def
#Include MISC.def
#Include TLV.def
#Include COMMANDS.DEF
#Include SHA.DEF

#Include eccard.def

Const UsedCurveIndex=17

Eeprom SharedSecret$
Eeprom prk$
Eeprom puk$

Eeprom prkCrc as Integer ' CRC over prk$
Eeprom pukCrc as Integer ' CRC over prk$

Const CrcPrk=1
Const CrcPuk=2
Const CrcBoth=CrcPuk OR CrcPrk

Declare Sub CheckKeyCrc(keyid as Integer)
Declare Sub UpdateKeyCrc(keyid as Integer)
Declare Function GetAsnInteger(Data$, Index%) as String

Call ECpSetCurve(UsedCurveIndex)

Rem  Command BaseECCARD &H00 GetCurveIndex (CurveIndex As Integer)
Rem
Rem  Return the Elliptic Curve domain parameters

Command BaseECCARD &H00 GetCurveIndex (CurveIndex As Integer)

  CurveIndex = UsedCurveIndex

End Command

Rem  Command BaseECCARD &H01 GenerateKey()
Rem
Rem  Call this command exactly once, to generate a private/public key pair

Command BaseECCARD &H01 GenerateKey()
  Call ECpGenerateKeyPair(prk$, puk$)
  If LibError <> 0 Then SW1SW2 = LibError : LibError = 0 : exit command
  UpdateKeyCrc CrcBoth
End Command

Rem  Command BaseECCARD &H02 SetPrivateKey (PrivateKey$, Disable Le)
Rem
Rem  Force the card to have the given private key

Command BaseECCARD &H02 SetPrivateKey (PrivateKey$, Disable Le)
  prk$=PrivateKey$
  'public key corresponding to private key PrK$ is returned in PuK$, in expanded format.
  Call ECpMakePublicKey(prk$, puk$) 
  If LibError <> 0 Then SW1SW2 = LibError : LibError = 0 : exit command
  UpdateKeyCrc CrcBoth
End Command

Rem  Command BaseECCARD &H03 GetPublicKey (PublicKey$)
Rem
Rem  This command returns the card's public key

Command BaseECCARD &H03 GetPublicKey (PublicKey$)
   CheckKeyCrc CrcPuk
   PublicKey$=puk$
End Command

Command BaseECCARD &H0A GetPrivateKey (Lc=0, PrivateKey$)
#Message *************************************************************************************************************************************************************************/!\ PrivateKey !!!
   CheckKeyCrc CrcPrk
   PrivateKey$=prk$
End Command

Command BaseECCARD &H07 SignDSA (Hash$)
  CheckKeyCrc CrcPrk
  Private Sig$
  Call ECpSignDSA(Hash$, prk$, Sig$)
  If LibError <> 0 Then SW1SW2 = LibError : LibError = 0 : exit command
  Hash$ = Sig$
End Command

Rem  Command BaseECCARD &H09 ECVerifyDSA (Asn1SignaturePublicKeyHash$, Disable Le)
Rem  Disable Le defines the command as having no outgoing data
Rem  Returns SW1SW2 = &H6B00 if verification fails

Command BaseECCARD &H09 ECVerifyDSA (Asn1SignaturePublicKeyHash$, Disable Le)
   Private Signature$, PublicKey$, Hash$
   Signature$ = GetAsnInteger(Asn1SignaturePublicKeyHash$, 1)
   PublicKey$ = GetAsnInteger(Asn1SignaturePublicKeyHash$, 2)
   Hash$ = GetAsnInteger(Asn1SignaturePublicKeyHash$, 1)
   Asn1SignaturePublicKeyHash$ = ""

   If Not ECpVerifyDSA (Hash$, PublicKey$, Signature$) Then SW1SW2 = swVerifyFail

End Command


Sub CheckKeyCrc(keyid as Integer)
   Private CRC%
   if 0<>(keyid AND CrcPrk) then
      CRC%=0
      Call UpdateCCITTCRC16(CRC%, prk$)
      if CRC%<>prkCrc then SW1SW2=swInternalError : exit
   end if
   if 0<>(keyid AND CrcPuk) then
      CRC%=0
      Call UpdateCCITTCRC16(CRC%, puk$)
      if CRC%<>pukCrc then SW1SW2=swInternalError : exit
   end if
End Sub

Sub UpdateKeyCrc(keyid as Integer)
   if 0<>(keyid AND CrcPrk) then
      prkCrc=0
      Call UpdateCCITTCRC16(prkCrc, prk$)
   end if
   if 0<>(keyid AND CrcPuk) then
      pukCrc=0
      Call UpdateCCITTCRC16(pukCrc, puk$)
   end if
End Sub

Function GetAsnInteger(Data$, Index%) as String
   LibError=0
   Private Seq as TlvPointer
   Private Item as TlvPointer
   GetAsnInteger=""
   Seq.Start=1
   Call TlvReadTagLength(Seq, Data$)
   if 0<>LibError then exit function
   Item.Info=0
   Call TlvMatchingChild(Seq, Item, Data$, 2, Index%)
   if 0<>LibError then exit function
   GetAsnInteger=TlvGetValue(Item, Data$)
End Function
